# -*- coding: utf-8 -*-
import base64
import json
from collections import OrderedDict

import requests
from Crypto.Hash import MD5
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5
from django.conf import settings

from async import async_job
from common.order import db as order_db
from common.order.model import PAY_STATUS
from common.utils import track_logging
from common.utils.exceptions import ParamError
from common.utils.tz import now_ts

_LOGGER = track_logging.getLogger(__name__)

APP_CONF = {
    '126107': {
        'API_KEY': '',
    }
}

_GATEWAY = 'http://api.xueyuplus.com/wbsp/unifiedorder'
_QUERY_GATEWAY_ = 'http://api.xueyuplus.com/wbsp/querydorder'

_fuyingbao_key = '''-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJuWvoRtBJ3fLiS2NeYbM7jq9/a+i/4pcWUAJUFaPWJ6Wy0LO77LDztN23wqm3Wyjh69MxJwKNbHa5ieEjcxjM0AGTaIjAaWZq+57K9sZXlPmBSRiAyxI03iVtLqB/ZWDNjsMlKHho268PYAgGgtJBZWVWVNv07Flv3kynJTNkSwIDAQAB
-----END PUBLIC KEY-----
'''

_my_public_key = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCu8BXMMpUZmoNjmOKkCqSbM4uy
YatSzq+2C+dYJZrZm8255gdP4wsByGw65HvCGCKiBOHbGxseIhfjGjXoJ+p5ufiK
QMtklghfrAo1cTW9byoReJkvyAMsfEp1RgKCTd4uP/9hSX5QHmYXyz+9cvBjy4Bw
nfRU5brJfvtm/EuWkwIDAQAB
-----END PUBLIC KEY-----"""

_my_private_key = """-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK7wFcwylRmag2OY
4qQKpJszi7Jhq1LOr7YL51glmtmbzbnmB0/jCwHIbDrke8IYIqIE4dsbGx4iF+Ma
Negn6nm5+IpAy2SWCF+sCjVxNb1vKhF4mS/IAyx8SnVGAoJN3i4//2FJflAeZhfL
P71y8GPLgHCd9FTlusl++2b8S5aTAgMBAAECgYBqf+slR14SGkkG51qC95/ChJz1
WhSM8xtxvsl2ll4xQHL8S5gEAHsA+N069UKKpVrgPAyr8VKPA757GcfbsAFEXCkc
RqJyj6MHeLXdFzQlo7sqsGlozIdV28eIjwl+MoJkjEP4HIkfFyd6QChAjdtrHTOP
bgsQt7DvJpvi+jsDQQJBANs3AQBxs5eS7KY4FJBLLAObuad5iQbBSjqrJ4vOw/Jm
MPjpUV/e4UooXtnDG5s/7qkR7Z/aZ5lfe5OscxsJ/xECQQDMSwk1RWUqNUqZ8Lxa
Xry+g7Bt9uzmI0MwBQoOho7dBitN739V/LqueINRVMt76OpRptsrNILvkMKVmtXP
5MNjAkAHLZvoydBZrEP3hWqW9v8v9w9zPnWQNRAbL7ORzml4LIR6AhnaC9BQv1Wr
x8nFoahM/PtM+rfdu9SuFz2FqyQhAkBH6T3Th5rlsZ6R84CJmwF7WmWXP60CEXWM
CKoSlODjAlHp/Bzpiq23zmoDDgMWmdUpar+JRNG2PFGSUc9jf5YbAkEA2w/46pcX
GHlH3vSYHkTHwqZUNjwJoyR+xX+HGeLEm7ffoKcFxTQbeYPY5DajQcyV6/F4n0t/
FFUwPhodE/YuFA==
-----END PRIVATE KEY-----"""


def _gen_sign(message, the_key):
    key = RSA.importKey(the_key)
    h = MD5.new(message)
    signer = Signature_pkcs1_v1_5.new(key)
    signature = signer.sign(h)
    signature = base64.b64encode(signature)
    return signature


def check_notify_sign(request, app_id):
    _LOGGER.info("fuyingbao notify body: %s", request.body)
    tmp_json = json.loads(request.body)
    _LOGGER.info("fuyingbao notify data: %s", tmp_json)
    _verify_response(tmp_json)
    pay_id = tmp_json['out_trade_no']
    if not pay_id:
        _LOGGER.error("fatal error, out_trade_no not exists, data: %s" % tmp_json)
        raise ParamError('fuyingbao event does not contain pay ID')

    pay = order_db.get_pay(int(pay_id))
    if not pay:
        raise ParamError('pay_id: %s invalid' % pay_id)
    if pay.status != PAY_STATUS.READY:
        raise ParamError('pay %s has been processed' % pay_id)

    mch_id = tmp_json['seller_id']
    trade_status = int(tmp_json['pay_status'])
    trade_no = ''
    total_fee = float(tmp_json['total_fee']) / 100.00

    extend = {
        'trade_status': trade_status,
        'trade_no': trade_no,
        'total_fee': total_fee
    }

    from common.channel.pay import check_channel_order
    check_channel_order(pay_id, total_fee, app_id)
    if trade_status == 1:
        _LOGGER.info('fuyingbao check order success, mch_id:%s pay_id:%s' % (mch_id, pay_id))
        res = order_db.add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
    async_job.notify_mch(pay_id)


def generate_sign_str(parameter):
    s = ''
    for k in sorted(parameter.keys()):
        if k != 'sign':
            s += '%s=%s&' % (k, parameter[k])
    return s[:len(s) - 1]


def _gen_sign(message):
    key = RSA.importKey(_my_private_key)
    h = MD5.new(message)
    signer = Signature_pkcs1_v1_5.new(key)
    signature = signer.sign(h)
    return base64.b64encode(signature)


def _verify_sign(data, signature, key):
    key = RSA.importKey(key)
    h = MD5.new(data)
    verifier = Signature_pkcs1_v1_5.new(key)
    if verifier.verify(h, base64.b64decode(signature)):
        return True
    return False


def _verify_response(rsp_json):
    sign = rsp_json['sign']
    s = generate_sign_str(rsp_json).encode('utf8')
    if not _verify_sign(s, sign, _fuyingbao_key):
        _LOGGER.info("fuyingbao verify sign not pass,  %s", rsp_json)
        raise ParamError('sign not pass, data: %s' % rsp_json)


def _get_pay_type(service):
    #	必填，微信二维码:2701;支付宝二维码:2702;银联快捷:2703;网银网关:2704;QQ钱包:2705;微信H5:2706;QQH5:2707;支付宝H5:2708
    if service == 'wxpay':
        payType = '2701'
    elif service == 'alipay':
        payType = '2702'
    elif service == 'quickbank':
        payType = '2703'
    elif service == 'bank':
        payType = '2704'
    elif service == 'qq':
        payType = '2705'
    elif service == 'wxpay_h5':
        payType = '2706'
    elif service == 'qq_h5':
        payType = '2707'
    elif service == 'alipay_h5':
        payType = '2708'
    else:
        payType = '2701'
    return payType


def _get_device_ip(info):
    try:
        extra = json.loads(info['extra'])
    except:
        extra = {}
    user_info = extra.get('user_info', {})
    return user_info.get('device_ip') or '127.0.0.1'


def create_charge(pay, pay_amount, info):
    ''' 创建订单 '''
    app_id = info['app_id']
    service = info.get('service')
    payType = _get_pay_type(service)

    p_dict = OrderedDict((
        ('seller_id', app_id),
        ('order_type', payType),
        ('out_trade_no', str(pay.id)),
        ('pay_body', 'pay'),
        ('total_fee', str(int(pay_amount * 100))),
        ('notify_url', '{}/pay/api/{}/fuyingbao/{}'.format(settings.NOTIFY_PREFIX, settings.NOTIFY_PATH, app_id)),
        ('spbill_create_ip', _get_device_ip(info)),
        ('spbill_times', str(now_ts())),
        ('noncestr', 'llllll'),
        ('remark', 'fuyingbao'),
    ))
    s = generate_sign_str(p_dict)
    p_dict['sign'] = _gen_sign(s)
    headers = {'Content-Type': 'application/json;charset=utf-8'}
    response = requests.post(_GATEWAY, data=json.dumps(p_dict), headers=headers, timeout=10)
    _LOGGER.info("fuyingbao create order : %s", response.text.encode('utf8'))
    j = json.loads(response.text)
    _verify_response(j)
    return {'charge_info': j['pay_url']}


def query_charge(pay_order, app_id):
    p_dict = OrderedDict((
        ('seller_id', app_id),
        ('out_trade_no', str(pay_order.id)),
    ))
    s = generate_sign_str(p_dict)
    p_dict['sign'] = _gen_sign(s)
    headers = {'Content-Type': 'application/json;charset=utf-8'}
    response = requests.post(_QUERY_GATEWAY_, data=json.dumps(p_dict), headers=headers, timeout=10)
    res_obj = json.loads(response.text)
    print res_obj
    _verify_response(res_obj)
    result = int(res_obj['pay_status'])
    order_id = res_obj['out_trade_no']
    total_fee = float(res_obj['total_fee']) / 100.0
    if str(order_id) != str(pay_order.id):
        _LOGGER.warn('fuyingbao query order, oder id ilegal! {}-{}'.format(
            order_id, pay_order.id))
        return

    if result == 1:
        trade_no = order_id
        extend = {
            'trade_status': result,
            'trade_no': order_id,
            'total_fee': total_fee
        }
        _LOGGER.info('fuyingbao query order success, mch_id:%s pay_id:%s',
                     pay_order.mch_id, pay_order.id)
        res = order_db.add_pay_success(pay_order.mch_id, pay_order.id,
                                       total_fee, trade_no, extend)
        if res:
            # async notify
            async_job.notify_mch(pay_order.id)
    else:
        _LOGGER.warn('fuyingbao query order fail, status_code: %s', result)
